"""
视频切分命令

提供视频镜头检测和切分的CLI接口。
"""

import click
import asyncio
from pathlib import Path
from typing import Optional

from rich.console import Console
from rich.progress import (
    Progress,
    SpinnerColumn,
    TextColumn,
    BarColumn,
    TimeElapsedColumn,
)
from rich.table import Table
from rich.panel import Panel

from ...services import ShotDetectionService, VideoSegmentationService

console = Console()


def _run_async_safe(coro):
    """安全地运行异步协程"""
    try:
        # 尝试获取当前事件循环
        loop = asyncio.get_running_loop()
        # 如果已经在事件循环中，使用线程池运行
        import concurrent.futures
        with concurrent.futures.ThreadPoolExecutor() as executor:
            future = executor.submit(asyncio.run, coro)
            return future.result()
    except RuntimeError:
        # 没有运行的事件循环，可以直接使用 asyncio.run
        return asyncio.run(coro)


@click.group()
def segment():
    """视频切分相关命令"""
    pass


@segment.command()
@click.argument("video_path", type=click.Path(exists=True))
@click.option(
    "--algorithm",
    "-a",
    type=click.Choice(
        [
            "frame_diff",
            "histogram",
            "enhanced_frame_diff",
            "multi_channel_histogram",
            "adaptive_histogram",
            "auto",
            "ensemble",
        ]
    ),
    default="multi_channel_histogram",
    help="检测算法",
)
@click.option(
    "--output-dir",
    "-o",
    type=click.Path(),
    default="output/shot_detection",
    help="输出目录",
)
@click.option("--threshold", "-t", type=float, help="检测阈值")
@click.option("--save-results/--no-save-results", default=True, help="是否保存检测结果")
def detect(
    video_path: str,
    algorithm: str,
    output_dir: str,
    threshold: Optional[float],
    save_results: bool,
):
    """检测视频中的镜头边界"""
    _run_async_safe(
        _detect_shots(video_path, algorithm, output_dir, threshold, save_results)
    )


async def _detect_shots(
    video_path: str,
    algorithm: str,
    output_dir: str,
    threshold: Optional[float],
    save_results: bool,
):
    """执行镜头检测"""
    console.print(f"🎬 开始检测视频镜头: {video_path}", style="bold blue")

    # 准备配置
    config = {}
    if threshold:
        config[algorithm] = {"threshold": threshold}

    try:
        with Progress(
            SpinnerColumn(),
            TextColumn("[progress.description]{task.description}"),
            BarColumn(),
            TimeElapsedColumn(),
            console=console,
        ) as progress:

            task = progress.add_task(f"使用 {algorithm} 算法检测中...", total=None)

            with ShotDetectionService(config) as service:
                result = await service.detect_shots(
                    video_path=video_path,
                    algorithm=algorithm,
                    output_dir=output_dir,
                    save_results=save_results,
                )

            progress.update(task, completed=True)

        # 显示结果
        _display_detection_result(result, video_path)

        if save_results:
            console.print(f"✅ 结果已保存到: {output_dir}", style="green")

    except Exception as e:
        console.print(f"❌ 检测失败: {e}", style="red")


def _display_detection_result(result, video_path: str):
    """显示检测结果"""
    # 创建结果表格
    table = Table(title="镜头检测结果")
    table.add_column("序号", style="cyan", no_wrap=True)
    table.add_column("帧号", style="magenta")
    table.add_column("时间 (秒)", style="green")
    table.add_column("置信度", style="yellow")
    table.add_column("类型", style="blue")

    for i, boundary in enumerate(result.boundaries[:20]):  # 只显示前20个
        table.add_row(
            str(i + 1),
            str(boundary.frame_number),
            f"{boundary.timestamp:.2f}",
            f"{boundary.confidence:.3f}",
            boundary.boundary_type,
        )

    if len(result.boundaries) > 20:
        table.add_row("...", "...", "...", "...", "...")

    console.print(table)

    # 显示统计信息
    stats_panel = Panel(
        f"算法: {result.algorithm_name}\n"
        f"总帧数: {result.frame_count}\n"
        f"检测到的镜头边界: {len(result.boundaries)}\n"
        f"处理时间: {result.processing_time:.2f}秒\n"
        f"平均置信度: {sum(b.confidence for b in result.boundaries) / len(result.boundaries) if result.boundaries else 0:.3f}",
        title="统计信息",
        style="blue",
    )
    console.print(stats_panel)


@segment.command()
@click.argument("video_path", type=click.Path(exists=True))
@click.option(
    "--method",
    "-m",
    type=click.Choice(["shots", "scenes", "smart", "time_based"]),
    default="shots",
    help="切分方法",
)
@click.option(
    "--output-dir",
    "-o",
    type=click.Path(),
    default="output/video_segments",
    help="输出目录",
)
@click.option(
    "--segment-duration", "-d", type=float, default=3.0, help="时间切分的片段长度（秒）"
)
@click.option(
    "--generate-files/--no-generate-files", default=True, help="是否生成视频文件"
)
@click.option(
    "--preset",
    "-p",
    type=click.Choice(["high_quality", "fast", "auto", "max_precision"]),
    help="预设组合 (high_quality: smart+multi_channel_histogram, fast: shots+frame_diff, auto: smart+auto, max_precision: scenes+ensemble)",
)
def split(
    video_path: str,
    method: str,
    output_dir: str,
    segment_duration: float,
    generate_files: bool,
    preset: Optional[str],
):
    """切分视频为多个片段"""
    _run_async_safe(
        _split_video(
            video_path,
            method,
            output_dir,
            segment_duration,
            generate_files,
            preset,
        )
    )


async def _split_video(
    video_path: str,
    method: str,
    output_dir: str,
    segment_duration: float,
    generate_files: bool,
    preset: Optional[str],
):
    """执行视频切分"""
    console.print(f"✂️ 开始切分视频: {video_path}", style="bold blue")

    # 显示预设信息
    if preset:
        preset_info = {
            "high_quality": "smart + multi_channel_histogram (高质量)",
            "fast": "shots + frame_diff (快速)",
            "auto": "smart + auto (自动选择)",
            "max_precision": "scenes + ensemble (最高精度)",
        }
        console.print(f"🎯 使用预设: {preset} ({preset_info[preset]})", style="dim")

    try:
        with Progress(
            SpinnerColumn(),
            TextColumn("[progress.description]{task.description}"),
            BarColumn(),
            TimeElapsedColumn(),
            console=console,
        ) as progress:

            task = progress.add_task(f"使用 {method} 方法切分中...", total=None)

            with VideoSegmentationService() as service:
                kwargs = {}
                if method == "time_based":
                    kwargs["segment_duration"] = segment_duration
                kwargs["generate_files"] = generate_files

                result = await service.segment_video(
                    video_path=video_path,
                    output_dir=output_dir,
                    method=method,
                    preset=preset,
                    **kwargs,
                )

                # 保存结果
                await service.save_segmentation_result(result, output_dir)

            progress.update(task, completed=True)

        # 显示结果
        _display_segmentation_result(result, video_path)

        console.print(f"✅ 切分完成，结果保存到: {output_dir}", style="green")

    except Exception as e:
        console.print(f"❌ 切分失败: {e}", style="red")


def _display_segmentation_result(result, video_path: str):
    """显示切分结果"""
    video_name = Path(video_path).name
    # 创建片段表格
    table = Table(title=f"视频片段 - {video_name}")
    table.add_column("片段", style="cyan", no_wrap=True)
    table.add_column("开始时间", style="green")
    table.add_column("结束时间", style="green")
    table.add_column("时长", style="yellow")
    table.add_column("置信度", style="magenta")
    table.add_column("文件", style="blue")

    for segment in result.segments[:15]:  # 只显示前15个
        file_name = Path(segment.file_path).name if segment.file_path else "未生成"
        table.add_row(
            str(segment.segment_id),
            f"{segment.start_time:.2f}s",
            f"{segment.end_time:.2f}s",
            f"{segment.duration:.2f}s",
            f"{segment.confidence:.3f}",
            file_name,
        )

    if len(result.segments) > 15:
        table.add_row("...", "...", "...", "...", "...", "...")

    console.print(table)

    # 显示统计信息
    durations = [s.duration for s in result.segments]
    stats_panel = Panel(
        f"切分方法: {result.algorithm}\n"
        f"总片段数: {result.segment_count}\n"
        f"视频总时长: {result.total_duration:.2f}秒\n"
        f"处理时间: {result.processing_time:.2f}秒\n"
        f"片段时长统计:\n"
        f"  最短: {min(durations):.2f}秒\n"
        f"  最长: {max(durations):.2f}秒\n"
        f"  平均: {sum(durations)/len(durations):.2f}秒",
        title="切分统计",
        style="blue",
    )
    console.print(stats_panel)


@segment.command()
@click.argument("video_path", type=click.Path(exists=True))
@click.option(
    "--output-dir", "-o", type=click.Path(), default="output/analysis", help="输出目录"
)
def analyze(video_path: str, output_dir: str):
    """分析视频特征和最佳切分策略"""
    _run_async_safe(_analyze_video(video_path, output_dir))


async def _analyze_video(video_path: str, output_dir: str):
    """分析视频"""
    console.print(f"🔍 分析视频: {video_path}", style="bold blue")

    # 确保输出目录存在
    output_path = Path(output_dir)
    output_path.mkdir(parents=True, exist_ok=True)

    try:
        with Progress(
            SpinnerColumn(),
            TextColumn("[progress.description]{task.description}"),
            console=console,
        ) as progress:

            task = progress.add_task("分析视频特征中...", total=None)

            with VideoSegmentationService() as service:
                # 分析视频特征
                features = await service._analyze_video_features(video_path)

                # 测试不同算法
                # "shots", "scenes", "smart", "time_based", "ensemble"
                # 'auto', 'frame_diff', 'histogram', 'ensemble'
                algorithms = [
                    "auto",
                    "frame_diff",
                    "histogram",
                    "ensemble",
                    "enhanced_frame_diff",
                    "multi_channel_histogram",
                    "adaptive_histogram",
                ]
                results = {}

                for algorithm in algorithms:
                    progress.update(task, description=f"测试 {algorithm} 算法...")
                    detection_result = (
                        await service.shot_detection_service.detect_shots(
                            video_path, algorithm, save_results=False
                        )
                    )
                    results[algorithm] = detection_result

            progress.update(task, completed=True)

        # 显示分析结果
        _display_analysis_result(features, results, video_path)

        # 保存分析结果到文件
        await _save_analysis_result(features, results, video_path, output_dir)

        console.print(f"✅ 分析完成，结果已保存到: {output_dir}", style="green")

    except Exception as e:
        console.print(f"❌ 分析失败: {e}", style="red")


async def _save_analysis_result(features, results, video_path: str, output_dir: str):
    """保存分析结果到文件"""
    import json
    from datetime import datetime

    output_path = Path(output_dir)
    video_name = Path(video_path).stem
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")

    # 准备保存的数据
    analysis_data = {
        "video_info": {
            "path": video_path,
            "name": video_name,
            "analysis_time": datetime.now().isoformat(),
        },
        "features": features,
        "algorithm_results": {},
    }

    # 转换算法结果为可序列化的格式
    for algorithm, result in results.items():
        analysis_data["algorithm_results"][algorithm] = {
            "algorithm_name": result.algorithm_name,
            "frame_count": result.frame_count,
            "processing_time": result.processing_time,
            "boundary_count": len(result.boundaries),
            "boundaries": [
                {
                    "frame_number": b.frame_number,
                    "timestamp": b.timestamp,
                    "confidence": b.confidence,
                    "boundary_type": b.boundary_type,
                }
                for b in result.boundaries
            ],
        }

    # 保存JSON文件
    json_file = output_path / f"{video_name}_analysis_{timestamp}.json"
    with open(json_file, "w", encoding="utf-8") as f:
        json.dump(analysis_data, f, indent=2, ensure_ascii=False)

    # 保存文本报告
    report_file = output_path / f"{video_name}_report_{timestamp}.txt"
    with open(report_file, "w", encoding="utf-8") as f:
        f.write(f"视频分析报告\n")
        f.write(f"=" * 50 + "\n\n")
        f.write(f"视频文件: {video_path}\n")
        f.write(f"分析时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n")

        f.write(f"视频特征:\n")
        f.write(f"-" * 20 + "\n")
        f.write(f"时长: {features['duration']:.2f}秒\n")
        f.write(f"帧率: {features['fps']:.1f} FPS\n")
        f.write(f"总帧数: {features['frame_count']}\n")
        f.write(f"检测到的镜头数: {features['shot_count']}\n")
        f.write(f"平均镜头时长: {features['avg_shot_duration']:.2f}秒\n")
        f.write(f"平均置信度: {features['avg_confidence']:.3f}\n\n")

        f.write(f"算法性能比较:\n")
        f.write(f"-" * 20 + "\n")
        for algorithm, result in results.items():
            avg_confidence = (
                sum(b.confidence for b in result.boundaries) / len(result.boundaries)
                if result.boundaries
                else 0
            )
            f.write(f"{algorithm}:\n")
            f.write(f"  检测边界数: {len(result.boundaries)}\n")
            f.write(f"  处理时间: {result.processing_time:.2f}秒\n")
            f.write(f"  平均置信度: {avg_confidence:.3f}\n\n")

        # 推荐策略
        if features["avg_shot_duration"] < 3.0:
            strategy = "建议使用场景合并策略 (scenes)"
        elif features["shot_count"] < 10:
            strategy = "建议使用镜头切分策略 (shots)"
        else:
            strategy = "建议使用智能切分策略 (smart)"

        f.write(f"推荐切分策略:\n")
        f.write(f"-" * 20 + "\n")
        f.write(f"{strategy}\n")


def _display_analysis_result(features, results, video_path: str):
    """显示分析结果"""
    video_name = Path(video_path).name

    # 视频特征
    features_panel = Panel(
        f"文件: {video_name}\n"
        f"时长: {features['duration']:.2f}秒\n"
        f"帧率: {features['fps']:.1f} FPS\n"
        f"总帧数: {features['frame_count']}\n"
        f"检测到的镜头数: {features['shot_count']}\n"
        f"平均镜头时长: {features['avg_shot_duration']:.2f}秒\n"
        f"平均置信度: {features['avg_confidence']:.3f}",
        title="视频特征",
        style="green",
    )
    console.print(features_panel)

    # 算法比较
    table = Table(title="算法性能比较")
    table.add_column("算法", style="cyan")
    table.add_column("检测边界数", style="yellow")
    table.add_column("处理时间", style="green")
    table.add_column("平均置信度", style="magenta")
    table.add_column("推荐度", style="blue")

    for algorithm, result in results.items():
        avg_confidence = (
            sum(b.confidence for b in result.boundaries) / len(result.boundaries)
            if result.boundaries
            else 0
        )

        # 简单的推荐逻辑
        if len(result.boundaries) > 0 and avg_confidence > 0.5:
            recommendation = "⭐⭐⭐"
        elif len(result.boundaries) > 0:
            recommendation = "⭐⭐"
        else:
            recommendation = "⭐"

        table.add_row(
            algorithm,
            str(len(result.boundaries)),
            f"{result.processing_time:.2f}s",
            f"{avg_confidence:.3f}",
            recommendation,
        )

    console.print(table)

    # 推荐策略
    if features["avg_shot_duration"] < 3.0:
        strategy = "建议使用场景合并策略 (scenes)"
    elif features["shot_count"] < 10:
        strategy = "建议使用镜头切分策略 (shots)"
    else:
        strategy = "建议使用智能切分策略 (smart)"

    recommendation_panel = Panel(strategy, title="推荐切分策略", style="yellow")
    console.print(recommendation_panel)
